use std::{rc::Rc, cell::RefCell};

use crate::{rtda::Frame, instructions::base::{BytecodeReader, Instruction}};

// lstore指令的索引来自操作数，其他来自指令
// Store int into local variable
#[derive(Debug, Default)]
pub struct LSTORE {
    index: usize
}

impl Instruction for LSTORE {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.index = reader.read_u8() as usize;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _lstore(frame, self.index);
    }
}

impl LSTORE {
    pub fn set_index(&mut self, index: usize) {
        self.index = index;
    } 
}


#[derive(Debug, Default)]
pub struct LSTORE_0 { }

impl Instruction for LSTORE_0 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _lstore(frame, 0);
    }
}

#[derive(Debug, Default)]
pub struct LSTORE_1 { }

impl Instruction for LSTORE_1 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _lstore(frame, 1);
    }
}

#[derive(Debug, Default)]
pub struct LSTORE_2 { }

impl Instruction for LSTORE_2 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _lstore(frame, 2);
    }
}

#[derive(Debug, Default)]
pub struct LSTORE_3 { }

impl Instruction for LSTORE_3 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _lstore(frame, 3);
    }
}


// 通用加载，把变量从操作数栈顶弹出，存入局部变量表。
fn _lstore(frame: Rc<RefCell<Frame>>, index: usize) {
    let val = frame.borrow().get_operand_stack().borrow_mut().pop_long();
    frame.borrow().get_local_vars().borrow_mut().set_long(index, val);
}